package cn.chiship.sdk.third.service;

import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.exception.ExceptionUtil;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.PrintUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.third.core.model.ZfbMpConfigModel;
import cn.chiship.sdk.third.properties.ChishipZfbMpProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.diagnosis.DiagnosisUtils;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝相关业务实现
 * URL:<a href="https://opendocs.alipay.com/mini/03l3fq?pathHash=8f560c7e">开发文档</a>
 *
 * @author lijian
 */
@Component
public class ZfbMpService {
    protected static final Logger LOGGER = LoggerFactory.getLogger(ZfbMpService.class);
    private static final String ACCESS_TOKEN = "access_token";


    @Resource
    ChishipZfbMpProperties chishipZfbMpProperties;
    @Resource
    RedisService redisService;

    private ZfbMpConfigModel zfbMpConfigModel;

    private String accessToken = null;

    public ZfbMpService config() {
        this.zfbMpConfigModel = new ZfbMpConfigModel(
                chishipZfbMpProperties.getAppId(),
                chishipZfbMpProperties.getPrivateKey(),
                chishipZfbMpProperties.getPublicKey(),
                chishipZfbMpProperties.getAesDecryptKey()
        );
        return this;
    }

    public ZfbMpService config(ZfbMpConfigModel zfbMpConfigModel) {
        if (ObjectUtils.isEmpty(zfbMpConfigModel)) {
            LOGGER.info("支付宝小程序实例配置为空，将自动加载默认配置信息");
            return config();
        }
        this.zfbMpConfigModel = zfbMpConfigModel;
        return this;
    }

    public ZfbMpService token() {
        BaseResult baseResult = getToken();
        if (!baseResult.isSuccess()) {
            throw new BusinessException(baseResult.getData() + "-" + baseResult.getMessage());
        }
        this.accessToken = baseResult.getData().toString();
        return this;
    }

    /**
     * 获取接口调用凭据
     * URL:<a href="https://developer.work.weixin.qq.com/document/path/91039">文档</a>
     *
     * @return BaseResult
     */
    private BaseResult getToken() {

        return null;
    }

    /**
     * 换取授权访问令牌
     * <a href="https://opendocs.alipay.com/mini/84bc7352_alipay.system.oauth.token?scene=common&pathHash=c6cfe1ef">链接</a>
     *
     * @param code 授权码
     * @return 结果
     */
    public BaseResult getOauthToken(String code) {
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setCode(code);
            request.setGrantType("authorization_code");
            AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                JSONObject json = JSON.parseObject(response.getBody());
                json = json.getJSONObject("alipay_system_oauth_token_response");
                if (!json.containsKey("open_id")) {
                    return BaseResult.error("还未接入openid？");
                }
                Map<String, String> result = new HashMap<>(7);
                result.put("openId", json.getString("open_id"));
                result.put("userId", json.getString("user_id"));
                result.put("alipayUserId", json.getString("alipay_user_id"));
                return BaseResult.ok(result);
            } else {
                PrintUtil.console("换取授权访问令牌出错，诊断链接：" + DiagnosisUtils.getDiagnosisUrl(response));
                return BaseResult.error(response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            return BaseResult.error(e.getErrMsg());
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    /**
     * 解密开放数据
     * <a href="https://opendocs.alipay.com/common/02mse3">链接</a>
     *
     * @param encryptedData 敏感数据
     * @param sign          签名串
     * @return BaseResult
     */
    public BaseResult decryptingOpenData(String encryptedData, String sign) {
        String signType = "RSA2";
        String charset = "UTF-8";
        String encryptType = "AES";
        boolean signCheckPass;
        String signContent = encryptedData;
        String signVerKey = getZfbMpConfigModel().getPublicKey();
        String decryptKey = getZfbMpConfigModel().getAesDecryptKey();
        signContent = "\"" + signContent + "\"";
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVerKey, charset, signType);
        } catch (AlipayApiException e) {
            return BaseResult.error(e.getMessage());
        }
        if (!signCheckPass) {
            return BaseResult.error("验签失败");
        }
        try {
            String plainData = AlipayEncrypt.decryptContent(signContent, encryptType, decryptKey, charset);
            JSONObject json = JSON.parseObject(plainData);
            return BaseResult.ok(json);
        } catch (AlipayApiException e) {
            return BaseResult.error(e.getMessage());

        }
    }

    private AlipayConfig getAlipayConfig() {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId(zfbMpConfigModel.getAppId());
        alipayConfig.setPrivateKey(zfbMpConfigModel.getPrivateKey());
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(zfbMpConfigModel.getPublicKey());
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
    }


    public String getAccessToken() {
        if (StringUtil.isNullOrEmpty(accessToken)) {
            throw new BusinessException("token为空！请链式调用如下方法：config().token()获得Token");
        }
        return accessToken;
    }

    public ZfbMpConfigModel getZfbMpConfigModel() {
        return zfbMpConfigModel;
    }


}
